#pragma once
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
#include <string>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "nocopy.hpp"
#include "Log.hpp"
using namespace log_ns;

static const int gsocket=-1;
static const uint16_t glocalport=8888;//默认端口，端口号是16位
//枚举退出码
enum{
    SOCKET_ERRO=1,
    BIND_ERRO=2
};

class Udpserver:public nocopy
{
    public:
    //构造
    Udpserver(uint16_t  localport=glocalport)
    :_socket(gsocket)
    ,_localport(localport)
    ,_isrunning(false)
    {}
//初始化服务器
    void InitServer()
    {
        //1. 创建套接字
         _socket=::socket(AF_INET,SOCK_DGRAM,0);//SOCK_DGRAM表示这是一个UDP套接字
        if(_socket<0)
        {
            LOG(FATAL,"socket errno\n");
            exit(SOCKET_ERRO);
        }
            LOG(DEBUG,"socket success,_socket:%d\n",_socket);//期望值为3，0，1，2被占

        //bind端口号，文件描述符和端口信息绑定联系
        struct sockaddr_in local;//网络通信结构体填充
        //清空结构体，初始化
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;//地址类型，通过地址类型判断通信类别（网络or本地）
        local.sin_port=htons(_localport);//主机序列转网络序列，服务器端口号
      //  local.sin_addr.s_addr=inet_addr(_localip.c_str());//4字节Ip,网络序列的ip
        local.sin_addr.s_addr=INADDR_ANY;//网络地址任意
        //在内核中设定通信结构体必须调用bind,这里不调用bind函数，设置的结构体是一个临时变量
        int n=::bind(_socket,(struct sockaddr*)&local,sizeof(local));

        if(n<0)
        {
            LOG(FATAL,"bind errno\n");
            exit(BIND_ERRO);
        }
            LOG(DEBUG,"bind success\n");

    }
    void Start()
    {
       _isrunning=true;
       char inbuffer[1024];
       while(_isrunning)
       {
        struct sockaddr_in peer;//远端结构体
        socklen_t len=sizeof(peer);//远端结构体大小
        //不断读取数据
        ssize_t n=recvfrom(_socket,inbuffer,sizeof(inbuffer)-1,0,(struct sockaddr*)&peer,&len);

        if(n>0)
        {
           // InetAddr addr(peer);
            inbuffer[n]=0;
            std::cout<<"client says :"<< inbuffer<<std::endl;
            std::string echo_string="[upd_server echo]";
            echo_string+=inbuffer;

            //发送数据
            sendto(_socket,echo_string.c_str(),echo_string.size(),0,(struct sockaddr *)&peer,len);
        }
       }
    }
    ~Udpserver()
    {
        if(_socket>gsocket)::close(_socket);
    }
    private:
    //文件描述符
    int _socket; 
   uint16_t  _localport;
  // std::string _localip;
  //服务器的运行状况
   bool _isrunning;
};